package com.fowo.api.service.handleWork;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fowo.api.datainterface.util.k3cloud.domain.Authentication;
import com.fowo.api.datainterface.util.k3cloud.domain.BillQuery;
import com.fowo.api.datainterface.util.k3cloud.domain.BillSave;
import com.fowo.api.datainterface.util.k3cloud.domain.BillSubmit;
import com.fowo.api.datainterface.util.k3cloud.service.BillQueryService;
import com.fowo.api.datainterface.util.k3cloud.service.BillSaveService;
import com.fowo.api.datainterface.util.k3cloud.service.BillSubmitService;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

/**
 * 简化k3cloud操作
 * 
 * @author dong.tang
 *
 */
public class K3CloudTemplate implements K3CloudOperations {

	private final BillQueryService billQueryService;
	
	private final BillSaveService billSaveService;
	
	private final BillSubmitService billSubmitService;
	
	private final ObjectMapper objectMapper;

	public K3CloudTemplate(String endPoint, Authentication auth) {
		this.billQueryService = new BillQueryService();
		this.billSaveService = new BillSaveService();
		this.billSubmitService = new BillSubmitService();
		this.billQueryService.setEndPoint(endPoint);
		this.billQueryService.setAuth(auth);
		this.billSaveService.setEndPoint(endPoint);
		this.billSaveService.setAuth(auth);
		this.billSubmitService.setEndPoint(endPoint);
		this.billSubmitService.setAuth(auth);
		this.objectMapper = new ObjectMapper();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T executeBillQuery(List<BillQuery> params, Class<T> type) {
		String result = billQueryService.execute(params);
		ObjectMapper m = new ObjectMapper();
		try {
			return m.readValue(result, type);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return (T) result;
	}
	
	@SuppressWarnings("unchecked")
    @Override
    public <T> List<T> executeBillQuery(BillQuery billQuery, Class<T> type) {
        Assert.notNull(billQuery, "the billQuery param must be not null");
        List<BillQuery> params = new ArrayList<>(1);
        params.add(billQuery);
        List<List<?>> billList = executeBillQuery(params, List.class);
        // mapper key-value
        String[] fields = billQuery.getFields();
        List<T> dataList = billList.parallelStream().map(list -> {
            Map<String, Object> bill = new HashMap<>();
            for(int i = 0; i < fields.length; i++) {
                bill.put(fields[i], list.get(i));
            }
            return objectMapper.convertValue(bill, type);
        }).collect(toList());
        return dataList;
    }
	
	@SuppressWarnings("unchecked")
	public <T> T executeBillSave(BillSave billSave, Class<T> type) {
		Assert.notNull(billSave, "the billSave param must be not null");
		List<Object> params = new ArrayList<>(2);
		params.add(billSave.getFormId());
		params.add(billSave.getModel());
		String result = billSaveService.execute(params);
		try {
			return objectMapper.readValue(result, type);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return (T) result;
    }

	@SuppressWarnings("unchecked")
	@Override
	public <T, N> T executeBillSubmit(BillSubmit<N> billSubmit, Class<T> type) {
		Assert.notNull(billSubmit, "the billSubmit param must be not null");
		List<Object> params = new ArrayList<>(2);
		params.add(billSubmit.getFormId());
		params.add(billSubmit);
		String result = this.billSubmitService.execute(params);
		try {
			return objectMapper.readValue(result, type);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return (T) result;
	}

}
